package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

// 定义结构体
type Product struct {
	ID    int
	Name  string
	Price float64
}

type Order struct {
	ID       int
	Product  Product
	Quantity int
	Total    float64
}

type Store struct {
	Products map[int]Product
	Orders   map[int]Order
	mutex    sync.Mutex
}

// 定义接口
type OrderProcessor interface {
	CreateOrder(productID int, quantity int) (Order, error)
	GetOrder(orderID int) (Order, bool)
	ListOrders() []Order
}

// 实现接口
func (s *Store) CreateOrder(productID int, quantity int) (Order, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	product, exists := s.Products[productID]
	if !exists {
		return Order{}, fmt.Errorf("产品ID %d 不存在", productID)
	}

	orderID := len(s.Orders) + 1
	total := product.Price * float64(quantity)
	order := Order{
		ID:       orderID,
		Product:  product,
		Quantity: quantity,
		Total:    total,
	}

	s.Orders[orderID] = order
	return order, nil
}

func (s *Store) GetOrder(orderID int) (Order, bool) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	order, exists := s.Orders[orderID]
	return order, exists
}

func (s *Store) ListOrders() []Order {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	orders := make([]Order, 0, len(s.Orders))
	for _, order := range s.Orders {
		orders = append(orders, order)
	}
	return orders
}

// 模拟支付服务
func processPayment(order Order, paymentChan chan<- bool) {
	fmt.Printf("处理订单 #%d 的支付...\n", order.ID)

	// 模拟支付处理时间
	time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)

	// 模拟支付成功/失败
	success := rand.Float32() > 0.1 // 90% 成功率
	paymentChan <- success
}

// 模拟发货服务
func shipOrder(order Order, shippingChan chan<- string) {
	fmt.Printf("准备发货订单 #%d...\n", order.ID)

	// 模拟发货处理时间
	time.Sleep(time.Duration(rand.Intn(1500)) * time.Millisecond)

	trackingNumber := fmt.Sprintf("TRK-%d", rand.Intn(1000000))
	shippingChan <- trackingNumber
}

func main() {
	fmt.Println("17. 综合示例：电子商务订单系统")

	// 初始化商店
	store := &Store{
		Products: make(map[int]Product),
		Orders:   make(map[int]Order),
	}

	// 添加产品
	store.Products[1] = Product{ID: 1, Name: "笔记本电脑", Price: 5999.99}
	store.Products[2] = Product{ID: 2, Name: "手机", Price: 3999.99}
	store.Products[3] = Product{ID: 3, Name: "平板电脑", Price: 2999.99}

	fmt.Println("\n--- 系统初始化完成 ---")
	fmt.Println("可用产品:")
	for _, product := range store.Products {
		fmt.Printf("  ID: %d, 名称: %s, 价格: %.2f\n", product.ID, product.Name, product.Price)
	}

	// 创建订单
	fmt.Println("\n--- 创建订单 ---")
	order1, err := store.CreateOrder(1, 2)
	if err != nil {
		fmt.Printf("创建订单失败: %v\n", err)
	} else {
		fmt.Printf("创建订单成功: #%d, 产品: %s, 数量: %d, 总价: %.2f\n",
			order1.ID, order1.Product.Name, order1.Quantity, order1.Total)
	}

	order2, err := store.CreateOrder(3, 1)
	if err != nil {
		fmt.Printf("创建订单失败: %v\n", err)
	} else {
		fmt.Printf("创建订单成功: #%d, 产品: %s, 数量: %d, 总价: %.2f\n",
			order2.ID, order2.Product.Name, order2.Quantity, order2.Total)
	}

	// 查询订单
	fmt.Println("\n--- 查询订单 ---")
	if order, exists := store.GetOrder(1); exists {
		fmt.Printf("查询到订单 #%d: %s x %d = %.2f\n",
			order.ID, order.Product.Name, order.Quantity, order.Total)
	} else {
		fmt.Println("未找到订单 #1")
	}

	// 列出所有订单
	fmt.Println("\n--- 所有订单 ---")
	orders := store.ListOrders()
	for _, order := range orders {
		fmt.Printf("订单 #%d: %s x %d = %.2f\n",
			order.ID, order.Product.Name, order.Quantity, order.Total)
	}

	// 并发处理订单 - 支付和发货
	fmt.Println("\n--- 并发处理订单 ---")

	// 创建通道用于接收处理结果
	paymentChan := make(chan bool)
	shippingChan := make(chan string)

	// 并发处理订单1的支付和发货
	go processPayment(order1, paymentChan)
	go shipOrder(order1, shippingChan)

	// 等待处理结果
	fmt.Println("等待订单处理结果...")

	// 使用 select 等待多个通道的结果
	for i := 0; i < 2; i++ {
		select {
		case paymentSuccess := <-paymentChan:
			if paymentSuccess {
				fmt.Printf("订单 #%d 支付成功!\n", order1.ID)
			} else {
				fmt.Printf("订单 #%d 支付失败!\n", order1.ID)
			}
		case trackingNumber := <-shippingChan:
			fmt.Printf("订单 #%d 发货完成，追踪号: %s\n", order1.ID, trackingNumber)
		case <-time.After(3 * time.Second):
			fmt.Println("处理超时!")
			return
		}
	}

	// 使用 WaitGroup 管理多个订单处理
	fmt.Println("\n--- 批量处理订单 ---")
	var wg sync.WaitGroup

	// 获取所有订单
	allOrders := store.ListOrders()

	// 为每个订单创建处理协程
	for _, order := range allOrders {
		wg.Add(1)
		go func(o Order) {
			defer wg.Done()

			// 为每个订单创建专用通道
			payChan := make(chan bool, 1)
			shipChan := make(chan string, 1)

			// 并发处理支付和发货
			go processPayment(o, payChan)
			go shipOrder(o, shipChan)

			// 等待处理结果
			paymentResult := <-payChan
			shippingResult := <-shipChan

			fmt.Printf("订单 #%d 处理完成 - 支付: %t, 发货追踪号: %s\n",
				o.ID, paymentResult, shippingResult)
		}(order)
	}

	// 等待所有订单处理完成
	wg.Wait()
	fmt.Println("所有订单处理完成!")

	// 错误处理示例
	fmt.Println("\n--- 错误处理示例 ---")

	// 尝试创建不存在的产品订单
	_, err = store.CreateOrder(999, 1)
	if err != nil {
		fmt.Printf("预期的错误: %v\n", err)
	}

	// 通道的实际应用场景
	fmt.Println("\n--- 通道的实际应用场景 ---")

	// 使用通道实现生产者-消费者模式
	jobs := make(chan int, 5)
	results := make(chan string, 5)

	// 启动3个工作者协程
	for w := 1; w <= 3; w++ {
		go worker(w, jobs, results)
	}

	// 发送任务
	go func() {
		for j := 1; j <= 5; j++ {
			fmt.Printf("发送任务 %d\n", j)
			jobs <- j
		}
		close(jobs)
	}()

	// 收集结果
	for i := 1; i <= 5; i++ {
		result := <-results
		fmt.Printf("收到结果: %s\n", result)
	}

	// 使用通道进行超时控制
	fmt.Println("\n--- 超时控制 ---")

	// 创建一个需要较长时间处理的通道操作
	longOp := make(chan string)

	go func() {
		time.Sleep(2 * time.Second)
		longOp <- "长时间操作完成"
	}()

	// 设置1秒超时
	select {
	case result := <-longOp:
		fmt.Printf("操作结果: %s\n", result)
	case <-time.After(1 * time.Second):
		fmt.Println("操作超时!")
	}

	fmt.Println("\n--- 综合示例完成 ---")
}

// 工作者函数
func worker(id int, jobs <-chan int, results chan<- string) {
	for job := range jobs {
		fmt.Printf("工作者 %d 正在处理任务 %d\n", id, job)
		// 模拟工作
		time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
		results <- fmt.Sprintf("工作者 %d 完成任务 %d", id, job)
	}
}
